/**
 * | -------------------------------------------------- |
 * |        Universidad Del Valle De Guatemala          |
 * | -------------------------------------------------- |
 * | Algoritmos y Estructuras de Datos.                 |
 * | Sección 20.                                        |
 * | Diego Bran, Eduardo Drummond, Javier García,       |
 * | Derek Orbaugh, Miguel Zea.                         |
 * | Hoja de Trabajo #3.                                |
 * | 27/07/2012.                                        |
 * | Descripción: implementación de un programa que     |
 * | evalúe el desempeño de distintos algoritmos de     |
 * | ordenamiento, sobre un arreglo de enteros de hasta |
 * | 2000 elementos.                                    |
 * | -------------------------------------------------- |
 */
package sort;
import java.util.Random;
import java.io.*;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 * Implementación de un programa de pruebas de rendimiento para algoritmos sort,
 * permite la generación de un archivo de números enteros aleatorios para luego
 * poder ser ordenados con cualquiera de los algoritmos de ordenamiento disponibles.
 */
public class SortTester extends javax.swing.JFrame {

    Random RandomGenerator = new Random(19580427);
    int size = 100; // Definición de tamaño por defecot de archivo a generar
    
    /**
     * Creates new form SortTester
     */
    public SortTester() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jFileChooser1 = new javax.swing.JFileChooser();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jToggleButton1 = new javax.swing.JToggleButton();
        jToggleButton2 = new javax.swing.JToggleButton();
        jToggleButton3 = new javax.swing.JToggleButton();
        jToggleButton4 = new javax.swing.JToggleButton();
        jToggleButton5 = new javax.swing.JToggleButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();
        jTextField1 = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jButton1.setText("Generar Archivo");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jButton2.setText("Ordenar Archivo");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jButton3.setText("Abrir Archivo");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jToggleButton1.setSelected(true);
        jToggleButton1.setText("Selection");
        jToggleButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleButton1ActionPerformed(evt);
            }
        });

        jToggleButton2.setText("Insertion");
        jToggleButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleButton2ActionPerformed(evt);
            }
        });

        jToggleButton3.setText("Bubble");
        jToggleButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleButton3ActionPerformed(evt);
            }
        });

        jToggleButton4.setText("Merge");
        jToggleButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleButton4ActionPerformed(evt);
            }
        });

        jToggleButton5.setText("Quick");
        jToggleButton5.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleButton5ActionPerformed(evt);
            }
        });

        jTextArea1.setColumns(20);
        jTextArea1.setRows(5);
        jScrollPane1.setViewportView(jTextArea1);

        jTextField1.setText("100");

        jLabel1.setText("Número de Datos:");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jButton2)
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 119, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButton3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(jToggleButton4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(jToggleButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 80, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(layout.createSequentialGroup()
                                        .addComponent(jToggleButton2)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(jToggleButton3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                        .addComponent(jToggleButton5, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addGap(89, 89, 89)))))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jTextField1)
                            .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton3)
                    .addComponent(jLabel1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jToggleButton1)
                    .addComponent(jToggleButton2)
                    .addComponent(jToggleButton3)
                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jToggleButton4)
                    .addComponent(jToggleButton5))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton2)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * Pre: el campo de texto de número de datos no está vacío.
     * Post: se genera un archivo de texto con un número de datos enteros
     * aleatorios especificado en el campo de texto, y  en la locación indicada
     * por el usuario (mediante un file chooser).
     * Para el manejo del SaveFileDialog se implementó el código proporcionado por
     * el sitio Java For Complete Begginers: 
     * http://www.homeandlearn.co.uk/java/save_file_dialogue_box.html
     * Para la generación de archivos de texto se empleó el código proporcionado
     * por el sitio de Rose India Technologies:
     * http://www.roseindia.net/java/beginners/WriteTextFileExample.shtml
     */
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        String text = "";
        
        // Se evalúa si el dato en el campo de texto es un número, si lo es, se
        // considera como el número de datos que deben generarse en el archivo.
        try {
            size = Integer.parseInt(jTextField1.getText());
        } catch (NumberFormatException ex) {
            jTextArea1.append("Número de datos incorrecto, se utilizará el valor por defecto de 100\n");
        }
        
        // Se genera una cadena que contenga el determinado número de datos enteros
        // aleatorios.
        for (int i = 0; i < size; i++) {
            text = text + String.valueOf(RandomGenerator.nextInt(5000)) + " ";
        }
        
        String file_name = "write.txt";                                         // Nombre por defecto del archivo de texto a crear.
        FileNameExtensionFilter ft = new FileNameExtensionFilter("Text Files", "txt"); //Filtro para el filechooser, sólo archivos de texto.
        jFileChooser1.addChoosableFileFilter(ft);
        int returnVal = jFileChooser1.showSaveDialog(this);                     // Se muestra el filechooser.
        if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
            File file = jFileChooser1.getSelectedFile();                        // Al momento que el usuario presiona aceptar, se almacena la dirección
            file_name = file.toString();                                        // del archivo creado.
        }
        
        Writer output = null;
        File file = new File(file_name + ".txt");                               // Se crea el archivo de texto en la dirección especificada por el filechooser.
        try {
            output = new BufferedWriter(new FileWriter(file));                  // Se escribe en el archivo la cadena de números aleatorios y se cierra el mismo.
            output.write(text);
            output.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            jTextArea1.append("Archivo creado exitosamente\n");                 // Se le hace saber al usuario la creación exitosa del archivo.
        }
    }//GEN-LAST:event_jButton1ActionPerformed

    /*
     * Pre: el archivo a abrir debe tener el formato: números enteros separados por
     * espacios.
     * Post: los contenidos del archivo de texto seleccionado son interpretados,
     * se ordenan los números enteros de manera ascendente y se reescribe el 
     * archivo de texto.
     * Para la lectura de archivos de texto se empleó el código proporcionado
     * por el sitio de Rose India Technologies:
     * http://www.roseindia.net/java/beginners/java-read-file-line-by-line.shtml
     */
    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        
        String file_name = "write.txt";
        FileNameExtensionFilter ft = new FileNameExtensionFilter("Text Files", "txt"); // Se utiliza el file chooser
        jFileChooser1.addChoosableFileFilter(ft);                               // de la misma manera que para la generación de archivos.
        int returnVal = jFileChooser1.showOpenDialog(this);                     // Se almacena la dirección del archivo de texto a abrir.
        if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
            File file = jFileChooser1.getSelectedFile();
            file_name = file.toString();
        }
        
        String ReadData = "";
        try{
            FileInputStream fstream = new FileInputStream(file_name);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            while ((strLine = br.readLine()) != null) {                         // Se lee línea por línea el archivo de texto especificado
                ReadData = ReadData + strLine;                                  // por la dirección obtenida por el filechooser, se almacena la
            }                                                                   // los datos y luego se cierra el mismo.
            in.close();
        } catch (Exception ex) {
            System.err.println("Error: " + ex.getMessage());
        } finally {
            String temp[];
            temp = ReadData.split(" ");                                         // Se separa la cadena leída en varias subcadenas, que contengan
            int IntData[] = new int[temp.length];                               // cada uno de los números aleatorios.
            for (int i = 0; i < temp.length; i++) {
                IntData[i] = Integer.parseInt(temp[i]);                         // Se convierte el arreglo de subcadenas a un arreglo de números enteros.
            }
            
            // Se seleccina el algoritmo de sort a emplear, en base a cuál de los
            // 5 botones toggle se encuentra activo.
            if (jToggleButton1.isSelected()) {
                Sorter.selectionSort(IntData);
                jTextArea1.append("Archivo ordenado exitosamente\n");
            } else if (jToggleButton2.isSelected()) {
                Sorter.insertionSort(IntData);
                jTextArea1.append("Archivo ordenado exitosamente\n");
            } else if (jToggleButton3.isSelected()) {
                Sorter.bubbleSort(IntData);
                jTextArea1.append("Archivo ordenado exitosamente\n");
            } else if (jToggleButton4.isSelected()) {
                Sorter.mergeSort(IntData);
                jTextArea1.append("Archivo ordenado exitosamente\n");
            } else if (jToggleButton5.isSelected()) {
                Sorter.quickSort(IntData);
                jTextArea1.append("Archivo ordenado exitosamente\n");
            }
            
            // Finalmente, se transforma el arreglo de números enteros ordenados a
            // una cadena y se prosigue a sobreescribir el archivo con los datos 
            // desordenados por uno con los datos ordenados ascendentemente.
            String text = "";
            for (int j = 0; j < IntData.length; j++) {
                text = text + String.valueOf(IntData[j]) + " ";
            }
            
            Writer output = null;
            File file = new File(file_name);
            try {
                output = new BufferedWriter(new FileWriter(file));
                output.write(text);
                output.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }//GEN-LAST:event_jButton2ActionPerformed

    /*
     * Pre: el archivo a abrir debe tener el formato: números enteros separados por
     * espacios.
     * Post: los contenidos del archivo de texto seleccionado se cargan en el
     * área de texto.
     * Para la lectura de archivos de texto se empleó el código proporcionado
     * por el sitio de Rose India Technologies:
     * http://www.roseindia.net/java/beginners/java-read-file-line-by-line.shtml
     */
    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        
        // Se realiza el mismo procedimiento que para la interpretación de datos, 
        // con la diferencia que las líneas leídas del archivo se adjuntan al texto
        // desplegado en el área de texto.
        String file_name = "write.txt";
        int returnVal = jFileChooser1.showOpenDialog(this);
        if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
            File file = jFileChooser1.getSelectedFile();
            file_name = file.toString();
        }
        
        try{
            FileInputStream fstream = new FileInputStream(file_name);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            while ((strLine = br.readLine()) != null) {
                jTextArea1.append(strLine + "\n");
            }
            in.close();
        } catch (Exception ex) {
            System.err.println("Error: " + ex.getMessage());
        }
    }//GEN-LAST:event_jButton3ActionPerformed

    /**
     * Pre: ninguna.
     * Post: se selecciona el botón toggle 2 y los demás se deseleccionan.
     */
    private void jToggleButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleButton2ActionPerformed
        if (jToggleButton2.isSelected()) {
            jToggleButton1.setSelected(false);
            jToggleButton3.setSelected(false);
            jToggleButton4.setSelected(false);
            jToggleButton5.setSelected(false);
        }
    }//GEN-LAST:event_jToggleButton2ActionPerformed

    /**
     * Pre: ninguna.
     * Post: se selecciona el botón toggle 1 y los demás se deseleccionan.
     */
    private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleButton1ActionPerformed
        if (jToggleButton1.isSelected()) {
            jToggleButton2.setSelected(false);
            jToggleButton3.setSelected(false);
            jToggleButton4.setSelected(false);
            jToggleButton5.setSelected(false);
        }
    }//GEN-LAST:event_jToggleButton1ActionPerformed

    /**
     * Pre: ninguna.
     * Post: se selecciona el botón toggle 3 y los demás se deseleccionan.
     */
    private void jToggleButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleButton3ActionPerformed
        if (jToggleButton3.isSelected()) {
            jToggleButton1.setSelected(false);
            jToggleButton2.setSelected(false);
            jToggleButton4.setSelected(false);
            jToggleButton5.setSelected(false);
        }
    }//GEN-LAST:event_jToggleButton3ActionPerformed

    /**
     * Pre: ninguna.
     * Post: se selecciona el botón toggle 4 y los demás se deseleccionan.
     */
    private void jToggleButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleButton4ActionPerformed
        if (jToggleButton4.isSelected()) {
            jToggleButton1.setSelected(false);
            jToggleButton2.setSelected(false);
            jToggleButton3.setSelected(false);
            jToggleButton5.setSelected(false);
        }
    }//GEN-LAST:event_jToggleButton4ActionPerformed

    /**
     * Pre: ninguna.
     * Post: se selecciona el botón toggle 5 y los demás se deseleccionan.
     */
    private void jToggleButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleButton5ActionPerformed
        if (jToggleButton5.isSelected()) {
            jToggleButton1.setSelected(false);
            jToggleButton2.setSelected(false);
            jToggleButton3.setSelected(false);
            jToggleButton4.setSelected(false);
        }
    }//GEN-LAST:event_jToggleButton5ActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(SortTester.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(SortTester.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(SortTester.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(SortTester.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new SortTester().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JFileChooser jFileChooser1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JToggleButton jToggleButton1;
    private javax.swing.JToggleButton jToggleButton2;
    private javax.swing.JToggleButton jToggleButton3;
    private javax.swing.JToggleButton jToggleButton4;
    private javax.swing.JToggleButton jToggleButton5;
    // End of variables declaration//GEN-END:variables
}
